/*
 * Copyright (c) 2002 David Corbin and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 * 	  David Corbin  - initial implementation - ALL access to perforce server 
 * 					should be through this interface.
 * 					- added moveFile method
 *    Boris Pruessmann - Migrated functionality from from IClientApi to 
 *                   IPerforceServer to achieve api separation.
 */
package net.sourceforge.perforce.core.api;

import java.io.InputStream;
import java.util.List;

import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.internal.api.FolderRepositoryRelation;
import net.sourceforge.perforce.core.resources.IChangelist;
import net.sourceforge.perforce.core.resources.RemoteFile;
import net.sourceforge.perforce.core.resources.RemoteResource;
import net.sourceforge.perforce.core.syncinfo.FolderSyncInfo;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.team.IResourceTree;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;

/** This interface describes the API used to access PerforceServer objects.
  * 
  * @version $Revision: 67 $
  * @author  <a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
  * @author  <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  * 
  * TODO: Check whether all thos methods need to be on the server interface, think about 
  * introducing a IPerforceProvider interface like they did with CVS.
  * 
  * TODO: Move from direct usage of client to connection object.
  * 
  * TODO: Use of IProgressMonitor.
  * 
  * TODO: Better typing for the parameters of most methods. String is not convenient.
  * 
  * TODO: Investigate change from throwing exceptions to passing status objects.
  */
public interface IPerforceServer
{
	// ------------------------------------------------------------------------------------- Methods
	
	/** Returns the toplevel members of the server. 
	  * 
	  * @param monitor for progress feedback.
	  * @return the top level members of the server.
	  * 
	  * @throws PerforceException in case of an error.
	  */	
	RemoteResource[] members(IProgressMonitor monitor)
		throws PerforceException;
		
	/** Call this method to retrieve the IFile that corresponds to the given
	  * filename (in any of the supported syntaxes).
	  * 
	  * @param filename path of the file.
	  * @return the corresponding IFile or null.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	IFile getFile(String filename)
		throws PerforceException;

	/** Call this method to retrieve the unique name of the server. This will be a combination
	  * of P4PORT, P4CLIENT and P4USER.
	  * 
	  * @return the unique server name.
	  */
	String getUniqueName();
	
	/** This method returns the P4PORT value that is associated with this server.
	  * 
	  * @return the P4PORT value.
	  */
	String getPort();
	
	/** This method returns the P4CLIENT value that is associated with this server.
	  * 
	  * @return the P4CLIENT value.
	  */
	String getClient();
	
	/** Returns the value of the associated P4USER.
	  * 
	  * @return the P4USER value.
	  */
	String getUser();
	
	/** Returns the value of the associated P4PASSWD.
	  *
	  * @return the P4PASSWD value. 
	  */
	String getPassword();

	/** Returns the address of the server.
	  * 
	  * @return the server address.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	String getServerAddress()
		throws PerforceException;
	
	/** Returns the root of the server.
	  * 
	  * @return the server root.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	String getServerRoot()
		throws PerforceException;
	
	/** Returns the date as currently set on the server.
	  *
	  * @return the server date as string.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	String getServerDate()
		throws PerforceException;
	
	/** Call this method to retrieve the server version. 
	  * 
	  * @return the server version.
	  * 
	  * @throws PerforceException in case of an error.
	  */				
	String getServerVersion()
		throws PerforceException;

	/** Returns the server's license info.
	  * 
	  * @return the license info.
	  * 
	  * @throws PerforceException in case of an error.	
	  */
	String getServerLicense()
		throws PerforceException;
	
	/** Call this method to check whether the given folder is under the perforce root or not.
	  * 
	  * @param folder the folder path.
	  * @return object providing detailed information.
	  */
	FolderRepositoryRelation determineFolderPosition(String folder);
	
	/** Returns the client form for the configured client.
	  * 
	  * @return the ClientForm.
	  * 
	  * @throws PerforceException in case of an unexpected error.
	  */
	IClientForm getClientForm()
		throws PerforceException;	
	
	/** Call this method to perform a perforce move of the given files.
	  * 
	  * @param tree the resource tree containing source and destination.
	  * @param src the file to move.
	  * @param destination the operation's destination.
	  * @param monitor for progress feedback,
	  * @return true if we handled the move.
	  */
	boolean moveFile(IResourceTree tree, IFile src, IFile destination, IProgressMonitor monitor);	

	/** Call this method to validate the server instanec, that is: check whether a connection
	  * to the server is possible with the given configuation.
	  * 
	  * @param monitor for progress feedback.
	  * 
	  * @throws PerforceException if it wasn't possible to connect to the server.
	  */
	void validateConnection(IProgressMonitor monitor)
		throws PerforceException;

	// --------------------------------------------------------------------------- Public P4 Methods

	/** Call this method to add the given files to the control of perforce.
	  * 
	  * @param fileNames array of filenames to be added.
	  * @param monitor monitor for progress feedack or null.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	void add(String[] fileNames, IProgressMonitor monitor)
		throws PerforceException;			

	/** Create a changelist description from the given changespec.
	  * 
	  * @param changeSpec the changespec description.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	void change(String changeSpec)
		throws PerforceException;

	/** Reads a changelist specification.
	  * 
	  * @param changelist the changelist number / id.
	  * @return the specification of the given changelist.
	  * 
	  * @throws PerforceException in case of an error.
	  */		
	IChangeResult change(Integer changelist)
		throws PerforceException;
		
	/** Retrieves list of pending and submitted changelists.
	  * 
	  * @param status either 'pending' or 'submitted'.
	  * @param count number of entries to fetch.
	  * @return array of changelist descriptions.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	IChangesResult[] changes(String status, int count)
		throws PerforceException;	

	/** Retrieves list of known counters.
	  * 
	  * @return object containing the values of all counters known to the server.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	ICountersResult counters()
		throws PerforceException;

	/** Opens the given filenames for delete.
	  * 
	  * @param fileNames array of files to be oepned for delete.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	void delete(String[] fileNames)
		throws PerforceException;

	/** Call this method to retrieve a list of depots as defined on the server.
	  * 
	  * @param monitor use for progress feedback.
	  * @return array of depot names.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	String[] depots(IProgressMonitor monitor)
		throws PerforceException;

	/** Calls this method to retrieve a changelist description.
	  *
	  * @param changelist the changelist number.
	  * @return a description of the given changelist.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	IDescribeResult describe(Integer changelist)
		throws PerforceException;

	/** Performs a 'p4 diff -sr' and returns a list of unchanged files.
	  * 
	  * @param files array of files to check.
	  * @return subset of files that do not differ from their server counterparts.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	String[] diff(String[] files)
		throws PerforceException;	

	/** List subdirectories of a given depot directory.
	  * 
	  * @param dir the name of the directory (might include wildcard)
	  * @param monitor for progress feedback
	  * @return array of FolderSyncInfo's.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	FolderSyncInfo[] dirs(String dir, IProgressMonitor monitor)
		throws PerforceException;

	/** Call this method to open the given files for edit.
	  * 
	  * @param fileNames array of filenames.
	  * @param monitor the progress monitor.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	void edit (String[] fileNames, IProgressMonitor monitor)
		throws PerforceException;
	
	/** Call this method to retrieve the history of the given remote file.
	  * 
	  * @param remoteFile the remote file.
	  * @param maxRevs number of revisions that we max. want to fetch.
	  * @param follow true if we want to follow branches.
	  * @return array of log entries.
	  * 
	  * @throws PerforceException in case of an error.
	  */	
	ILogEntry[] filelog(RemoteFile remoteFile, int maxRevs, boolean follow)
		throws PerforceException;
		
	/** Call this method to find all files matching the filespec.
	  *
	  * @param filespec the filespec.
	  * @param monitor for progress feedback.
	  * @return array of remote files.
	  * 
	  * @throws PerforceException in case of an error. 
	  */
	RemoteFile[] findAllFiles(String filespec, IProgressMonitor monitor)
		throws PerforceException;

	/** Tries to locat the specified resource.
	  *
	  * @param name name of the file or folder.
	  * @param monitor the progress monitor.
	  * @return the resource if found.  
	  * 
	  * @throws PerforceException in case of an error.
	  */
	RemoteResource find(String name, IProgressMonitor monitor)
		throws PerforceException;

	/** Call this method to retrieve ResourceSyncInfo for the given file spec.
	  * 
	  * @param file the name of the file (might include wildcard).
	  * @param monitor the progress monitor.
	  * @return array of ResourceSyncInfo.
	  * 
	  * @throws PerforceException in case of an exception.
	  */
	ResourceSyncInfo[] fstat(String file, IProgressMonitor monitor)
		throws PerforceException;

	/** Call this method to retrieve client/server information.
	  *  
	  * @param monitor used for progress feedback.
	  * @return the fetched info record.
	  * 
	  * @throws PerforceException in case of an unexpected error.
	  */
	IInfoResult info(IProgressMonitor monitor)
		throws PerforceException;

	/** Call this method to perform an 'p4 integrate' on the given file.
	  * 
	  * @param from the source of the integration.
	  * @param to the destination of the integration.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	void integrate(String from, String to)
		throws PerforceException;

	/** Returns list of files opened for pending changelist.
	  * 
	  * @param changelist the number of the changelist.
	  * @return array of opened files.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	IOpenedResult[] opened(IChangelist changelist)
		throws PerforceException;
		
	/** Returns list of files opened for ...
	  * 
	  * @param allClients get info for all clients.
	  * @return array of opened files.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	IOpenedResult[] opened(boolean allClients)
		throws PerforceException;
		
	/** Call this method to reopen the given files in the specified changelist.
	  * 
	  * @param changelist the number of the target changelist.
	  * @param filenames array of filenames.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	void reopen(Integer changelist, String[] filenames)
		throws PerforceException;

	/** Call this method to merge open files with other revisions.
	  * 
	  * @param spec specification of the file to resolve.
	  * @param simulate true if we only want to simulate the operation.
	  * @return array of resolve results.
	  * 
	  * @throws PerforceException in case of an error.
	  * 
	  * TODO: Implement/Fix non-simulating mode.
	  */
	IResolveResult[] resolve(String spec, boolean simulate)
		throws PerforceException;

	/** Checks whether the given file has been resolved or not.
	  * 
	  * @param filename name of the file.
	  * @return the other file used during resolve.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	String resolved(String filename)
		throws PerforceException;						

	/** Call this method to revert the given files.
	  * 
	  * @param fileNames array of file names to revert.
	  * @param monitor the progress monitor to use.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	void revert(String[] fileNames, IProgressMonitor monitor)
		throws PerforceException;
	
	/** Submits the given changespec.
	  * 
	  * @param changeSpec describing the changelist.
	  * @return array of files that have to be refreshed (ie. because of keyword substitution)
	  * 
	  * @throws PerforceException in case of an error.
	  */
	ISubmitResult[] submit(String changeSpec)
		throws PerforceException;		
	
	/** Performs a 'p4 sync' based on the given path and revision spec.
	  * 
	  * @param path the path specification.
	  * @param revisionSpec the revision specification.
	  * @param monitor used for progress feedback.
	  * @return status of the operation.
	  * 
	  * @throws PerforceException in case of an unexpected error.
	  */
	IStatus sync(String path, String revisionSpec, IProgressMonitor monitor)
		throws PerforceException;
	
	/** Performs a 'p4 sync' and adds the synced files to the list.
	  * 
	  * @param path the path specification.
	  * @param revisionSpec the revision specification.
	  * @param syncedFileList [out] the synced files.
	  * @param monitor used for progress feedback.
	  * @return status of the operation.
	  * 
	  * @throws PerforceException in case of an unexpected error.
	  */ 
	IStatus sync(String path, String revisionSpec, List syncedFileList, IProgressMonitor monitor)
		throws PerforceException;

	/** Simulates a 'p4 sync' operation.
	  * 
	  * @param syncSpec sync specification.
	  * @param simulate has to be true for the moment.
	  * @param monitor for progress feedback.
	  * @return array of files that would be synced.
	  * 
	  * @throws PerforceException in case of an unexpected error.
	  * 
	  * TODO: merge with sync(String)
	  */
	String[] sync(String syncSpec, boolean simulate, IProgressMonitor monitor)
		throws PerforceException;
	
	/**	Performs a 'p4 print', result will be in form of an InputStream.
	  * 
	  * @param depotFileName the name of the file.
	  * @param revision the revision spec.
	  * @return the InputStream.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	InputStream print(String depotFileName, String revision)
		throws PerforceException;		
		
	/** Show how file names map through the client view.
	  * 
	  * @param filename in any supported Perforce format (depot, client, local)
	  * @return object containing the representations of the filename.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	IWhereResult where(String filename)
		throws PerforceException;	

	/** Like where(String) but for multiple files.
	  * 
	  * @param filenames array of filenames.
	  * @return array of mappings.
	  * 
	  * @throws PerforceException in case of an error.
	  * 
	  * @see IPerforceServer#where(String)
	  */
	IWhereResult[] where(String[] filenames)
		throws PerforceException;

	/** Returns the mapping of the given resource.
	  * 
	  * @param resource the resource.
	  * @return the mapping.
	  * 
	  * @throws PerforceException in case of an error.
	  * 
	  * @see IPerforceServer#where(String)
	  */
	IWhereResult where(IResource resource)
		throws PerforceException;
		
	/** Gets ResourceSyncInfo from cache.
	  * 
	  * @param container the container for which we need the FolderSyncInfo.
	  * @return the folder sync info or null.
	  */	
	FolderSyncInfo getFolderSyncInfo(IContainer container);

	/** Wrapper for fstat().
	  * 
	  * @param container that contains resources for which we need ResourceSyncInfo's.
	  * @return array of ResourceSyncInfo.
	  */		
	ResourceSyncInfo[] getResourceSyncInfo(IContainer container);

	/** Puts ResourceSyncInfos into the cache.
	  * 
	  * @param syncInfos ResourceSyncInfos to store.
	  */
	void setResourceSyncInfos(ResourceSyncInfo[] syncInfos);
	
	/** Puts ResourceSyncInfos into the cache.
	 * 
	 * @param resource the resource.
	 * @param syncInfo the associated ResourceSyncInfo.
	 */
	void setResourceSyncInfo(IResource resource, ResourceSyncInfo syncInfo);

	/** Gets ResourceSyncInfo from cache.
	  * 
	  * @param file for which ResourceSyncInfo is requested.
	  * @return the associated resource sync info.
	  */		
	ResourceSyncInfo getResourceSyncInfo(IFile file);
}
